
#include <streams.h>
# include <libavcodec/avcodec.h>
# include <libavutil/avutil.h>
# include <libswscale/swscale.h>
#include "pixconv.h"
#include "VideoDecodecFilter.h"


CVideoDecodecFilter::CVideoDecodecFilter(TCHAR *tszName, LPUNKNOWN punk, HRESULT *phr):
CTransformFilter(tszName,punk,CLSID_VideoDecodecFilter)
{
	m_pDecode = new CPixConv();
	m_pDecode->init();
}

CVideoDecodecFilter::~CVideoDecodecFilter(void)
{
}

CUnknown* WINAPI CVideoDecodecFilter::CreateInstance(LPUNKNOWN punk,HRESULT *phr)
{
	CVideoDecodecFilter* pNewObject = new CVideoDecodecFilter(NAME("VideoDecodecFilter"),punk,phr);
	if(pNewObject == NULL)
	{
		if(phr)
		{
			*phr = E_OUTOFMEMORY;
		}
	}

	return pNewObject;
}

HRESULT CVideoDecodecFilter::CheckInputType(const CMediaType* mtIn)
{
	CheckPointer(mtIn,E_POINTER);

	if((mtIn->formattype != FORMAT_VideoInfo) ||
		(mtIn->majortype != MEDIATYPE_Video) ||
		(mtIn->cbFormat < sizeof(VIDEOINFOHEADER)) ||
		(mtIn->pbFormat == NULL))
		return VFW_E_TYPE_NOT_ACCEPTED;

	return S_OK;
}

HRESULT CVideoDecodecFilter::CheckTransform(const CMediaType* mtIn, const CMediaType* mtOut)
{
	CheckPointer(mtIn,E_POINTER);
	CheckPointer(mtOut,E_POINTER);

	HRESULT hr;
	if(FAILED(hr = CheckInputType(mtIn)))
	{
		return hr;
	}

	if((*mtOut->FormatType() != FORMAT_VideoInfo) ||
		(*mtOut->Type() != MEDIATYPE_Video) || 
		(mtOut->FormatLength() < sizeof(VIDEOINFOHEADER)) ||
		(mtOut->Format() == NULL))
	{
		return E_INVALIDARG;
	}
	VIDEOINFO* pVideoInfo = (VIDEOINFO*)mtOut->Format();
	VIDEOINFO* pInVideoInfo = (VIDEOINFO*)mtIn->Format();
	if(pVideoInfo->bmiHeader.biHeight != pInVideoInfo->bmiHeader.biHeight)
		return E_INVALIDARG;

	return NOERROR;
}

HRESULT CVideoDecodecFilter::GetMediaType(int iPosition, CMediaType *pMediaType)
{
	// Is the input pin connected

	if(m_pInput->IsConnected() == FALSE)
	{
		return E_UNEXPECTED;
	}

	// This should never happen

	if(iPosition < 0)
	{
		return E_INVALIDARG;
	}

	// Do we have more items to offer

	if(iPosition > 0)
	{
		return VFW_S_NO_MORE_ITEMS;
	}

	CheckPointer(pMediaType,E_POINTER);

	VIDEOINFO* pVideoInfo = NULL;
	HRESULT hr = m_pInput->ConnectionMediaType(pMediaType);	

	//m_mediaType = *pMediaType;
	return NOERROR;
}

HRESULT CVideoDecodecFilter::DecideBufferSize(IMemAllocator * pAlloc, ALLOCATOR_PROPERTIES *pProperties)
{
	CheckPointer(pAlloc,E_POINTER);
	CheckPointer(pProperties,E_POINTER);
	HRESULT hr = NOERROR;

	if(m_pInput->IsConnected() == FALSE)
	{
		return E_UNEXPECTED;
	}
	pProperties->cBuffers = 1;
	pProperties->cbAlign = 1;
	pProperties->cbBuffer = m_pInput->CurrentMediaType().GetSampleSize();


	ALLOCATOR_PROPERTIES Actual;

	hr = pAlloc->SetProperties(pProperties,&Actual);
	if(FAILED(hr))
	{
		return hr;
	}

	ASSERT(Actual.cBuffers == 1);

	if(pProperties->cBuffers > Actual.cBuffers ||
		pProperties->cbBuffer > Actual.cbBuffer)
	{
		return E_FAIL;
	}

	return NOERROR;
}

HRESULT CVideoDecodecFilter::Transform(IMediaSample * pIn, IMediaSample *pOut)
{
	CheckPointer(pIn,E_POINTER);
	CheckPointer(pOut,E_POINTER);

	PBYTE pSrcData,pDestData;
	HRESULT hr = S_OK;
	long lActualLen = 0;
	
	hr = pIn->GetPointer(&pSrcData);
	hr = pOut->GetPointer(&pDestData);
	lActualLen = pIn->GetActualDataLength();

	long len = m_pDecode->decodec(pSrcData,pDestData,lActualLen);
	pOut->SetActualDataLength(len);
	return hr;
}

/*STDMETHODIMP CVideoDecodecFilter::NonDelegatingQueryInterface(REFIID riid,void** ppv)
{
	//if(riid == IID_IEffectConvert)
	//	return GetInterface(static_cast<IEffectConvert*>(this),ppv);

	return CTransformFilter::NonDelegatingQueryInterface(riid,ppv);
}*/